﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Complex;
using System.Numerics;

namespace SpiceNet.Circuits
{
    /// <summary>
    /// A class describing the state of the circuit using complex numbers
    /// </summary>
    public class CircuitStateComplex
    {
        /// <summary>
        /// The current Omega (when doing AC-type solving)
        /// </summary>
        public Complex Omega = new Complex();

        /// <summary>
        /// Gets the order
        /// </summary>
        public int Order { get; private set; } = 0;

        /// <summary>
        /// Gets the (complex) Yn-matrix
        /// </summary>
        public Matrix<Complex> Matrix { get; private set; } = null;

        /// <summary>
        /// Gets the (complex) RHS vector
        /// </summary>
        public Vector<Complex> Rhs { get; private set; } = null;

        /// <summary>
        /// Gets the (complex) solution vector
        /// </summary>
        public Vector<Complex> Solution { get; private set; } = null;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="order"></param>
        public CircuitStateComplex() { }

        /// <summary>
        /// Initialize
        /// </summary>
        /// <param name="ckt"></param>
        public void Init(Circuit ckt)
        {
            Order = ckt.Nodes.Count;
            Matrix = new SparseMatrix(Order + 1);
            Rhs = new SparseVector(Order + 1);
            Solution = new DenseVector(Order + 1);
        }

        /// <summary>
        /// Solve the current matrix using the Rhs vector
        /// </summary>
        public void Solve()
        {
            // All indices at 0 are the ground node
            // We remove these rows/columns/items because they will lead to a singular matrix
            var m = Matrix.RemoveRow(0).RemoveColumn(0);
            var b = Rhs.SubVector(1, Rhs.Count - 1);

            // Create a new solution vector of the original size
            Solution = new DenseVector(Rhs.Count);

            // Fill the 1-N elements with the solution
            Solution.SetSubVector(1, Solution.Count - 1, m.Solve(b));
        }

        /// <summary>
        /// Solve the transposed matrix using the Rhs vector
        /// </summary>
        public void SolveTransposed()
        {
            // All indices at 0 are the ground node
            // We remove these rows/columns/items because they will lead to singular matrices
            var m = Matrix.RemoveRow(0).RemoveColumn(0);
            var b = Rhs.SubVector(1, Rhs.Count - 1);

            // Solve transposed matrix
            m = m.Transpose();

            // Create a new solution vector of the original size
            Solution = new DenseVector(Rhs.Count);

            // Fill the 1-N elements with the solution
            Solution.SetSubVector(1, Solution.Count - 1, m.Solve(b));
        }
    }
}
